#include "bsp_dec_font.h"

//根据首字节,获取utf8字符所占字节数
uint8_t bsp_get_utf8charbytenum(uint8_t u8Data)
{
    uint8_t u8byteNum = 0;
    if (u8Data >= 0xFC && u8Data < 0xFE)
        u8byteNum = 6;
    else if (u8Data >= 0xF8)
        u8byteNum = 5;
    else if (u8Data >= 0xF0)
        u8byteNum = 4;
    else if (u8Data >= 0xE0)
        u8byteNum = 3;
    else if (u8Data >= 0xC0)
        u8byteNum = 2;
    else if (0 == (u8Data & 0x80))
        u8byteNum = 1;
    
    return u8byteNum;
}
 
//判断字符串是否是utf8格式
uint8_t bsp_is_utf8format(const uint8_t *pu8str)
{
    uint32_t u32byteNum = 0;
    uint8_t u8ch;
    const uint8_t *pu8ptr = pu8str;
    
    if (NULL == pu8str)
        return 0;
    
    while (*pu8ptr != '\0')
    {
        u8ch = (uint8_t)*pu8ptr;
        if (u32byteNum == 0) //根据首字节特性判断该字符的字节数
        {
        if (0 == (u32byteNum = (uint32_t)bsp_get_utf8charbytenum(u8ch)))
            return 0;
        }
        else //多字节字符,非首字节格式:10xxxxxx
        {
        if ((u8ch & 0xC0) != 0x80)
            return 0;
        }
        u32byteNum--;
        pu8ptr++;
    }
    
    if (u32byteNum > 0)
        return 0;
    
    return 1;
}

#if 1
//计算utf8字符串字符个数
uint32_t bsp_get_utf8length(const uint8_t *pu8str)
{
    uint32_t u32srclen = 0;
    uint32_t u32strlen = 0;
    uint32_t u32byteNum = 0;
    uint8_t u8ch;
    
    if (NULL == pu8str)
        return 0;
 
    u32srclen = strlen((char *)pu8str);
    while (*pu8str != '\0' && u32strlen < u32srclen)
    {
        u8ch = (unsigned char)*pu8str;
        if (0 == (u32byteNum = bsp_get_utf8charbytenum(u8ch)))
        return 0;
        pu8str += u32byteNum;
        u32strlen++;
    }


    return u32strlen;
}
#else
//返回UTF8字符串长度
uint32_t bsp_get_utf8length(const uint8_t *pu8str)
{
    uint32_t u32srclen = 0;
    uint32_t u32strlen = 0;
    uint32_t u32byteNum = 0;
    uint32_t u32outlen = 0;
    uint8_t u8ch;
    
    if (NULL == pu8str)
        return 0;
 
    u32srclen = strlen((char *)pu8str);
    while (*pu8str != '\0' && u32strlen < u32srclen)
    {
        u8ch = (unsigned char)*pu8str;
        if (0 == (u32byteNum = bsp_get_utf8charbytenum(u8ch)))
        return 0;
        pu8str += u32byteNum;
        u32outlen += u32byteNum;
        u32strlen++;
    }


    return u32outlen;
}
#endif


//将utf8字符串转换为unicode编码
uint8_t bsp_utf8tounicode(uint8_t *u8utf8, uint32_t *u32unicode) 
{
    const uint8_t u8lutsize = 3;
    const uint8_t au8lutlen[] = {2, 3, 4};
    const uint8_t au8lutrange[] = {0xE0, 0xF0, 0xF8};
    const uint8_t au8lutmask[] = {0x1F, 0x0F, 0x07};

    uint8_t u8length = 0;
    uint8_t u8byte = *(u8utf8 + 0);
    uint32_t i = 0;

    if(u8utf8 == NULL) 
    {
        *u32unicode = 0;
        return 0;
    }
    // utf8编码兼容ASCII编码,使用0xxxxxx 表示00~7F
    if(u8byte < 0x80) 
    {
        *u32unicode =  u8byte;
        return 1;
    }
    // utf8不兼容ISO8859-1 ASCII拓展字符集
    // 同时最大支持编码6个字节即1111110X
    if(u8byte < 0xC0 || u8byte > 0xFD) {
        *u32unicode = 0;
        return 0;
    }
    for(i = 0; i < u8lutsize; i++) {
        if(u8byte < au8lutrange[i]) {
            *u32unicode = u8byte & au8lutmask[i];
            u8length = au8lutlen[i];
            break;
        }
    }
    // 超过四字节的utf8编码不进行解析
    if(u8length == 0) 
    {
        *u32unicode = 0;
        return 0;
    }
    // 取后续字节数据
    for(i = 1; i < u8length; i++ ) 
    {
        u8byte = *(u8utf8 + i);
        // 多字节utf8编码后续字节范围10xxxxxx~10111111
        if( u8byte < 0x80 || u8byte > 0xBF ) {
            break;
        }
        *u32unicode <<= 6;
        // 00111111
        *u32unicode |= (u8byte & 0x3F);
    }
    // 长度校验
    return (i < u8length) ? 0 : u8length;
}

uint8_t bsp_unicodetoutf16(uint32_t u32unicode, uint16_t *pu16utf16) 
{
    // Unicode范围 U+000~U+FFFF
    // utf16编码方式：2 Byte存储，编码后等于Unicode值
    if(u32unicode <= 0xFFFF) 
    {
		if(pu16utf16 != NULL) 
        {
			*pu16utf16 = (u32unicode & 0xFFFF);
		}
		return 1;
	}
    else if( u32unicode <= 0xEFFFF ) 
    {
		if( pu16utf16 != NULL ) 
        {
		    // 高10位
		    *(pu16utf16 + 0) = 0xD800 + (u32unicode >> 10) - 0x40;
            // 低10位
		    *(pu16utf16 + 1) = 0xDC00 + (u32unicode &0x03FF);
		}
		return 2;
	}
    return 0;
}



//将传入的utf8字符串转换为gb2312编码,放到固定SRAM中
void bsp_switch_utf8_to_gb2312(uint8_t *pu8utf8,uint16_t u16arrlen)
{
    uint32_t u32unicode = 0;
    uint16_t i = 0;
    uint16_t *pu16ArrLen = (uint16_t *)(FONT_SRC_MEM_LEN_START_ADDR);
    uint16_t *pu16Data = (uint16_t *)(FONT_SRC_MEM_START_ADDR);
    uint8_t  *pu8Data = NULL;
    uint16_t u16Temp;
    uint8_t u8chlen = 0;
    *pu16ArrLen = 0;

    while(i < u16arrlen)
    {
        if(pu8utf8[i] & 0x80)    //判断是否是utf8编码
        {
            bsp_utf8tounicode(pu8utf8+i, &u32unicode);
            bsp_unicodetoutf16(u32unicode,&u16Temp);  //转换成2字节的utf16码
            bsp_search_gb2312(&u16Temp);
            //大端转小端
            *pu16Data = ((u16Temp & 0xFF00) >> 8) | ((u16Temp & 0x00FF) << 8);  
            u8chlen = bsp_get_utf8charbytenum(pu8utf8[i]);
            i += u8chlen;
            (*pu16ArrLen) ++;
            pu16Data++;
        }
        else    //非utf8编码,ASCII码
        {
            pu8Data = (uint8_t *)pu16Data;
            *pu8Data = pu8utf8[i];
            i += 1;
            (*pu16ArrLen) ++;
            pu8Data++;
            pu16Data = (uint16_t *)pu8Data;
        }
        
    }
    return;
}

//二分法查表
uint8_t bsp_search_gb2312(uint16_t *pu16utf16)
{
    uint16_t u16AddrStart = 0;
    uint16_t u16AddrMid = 0x6CCC /2; 
    uint16_t u16AddrEnd   = 0x6CCB;
    uint16_t u16utf16 = *pu16utf16;
    uint16_t u16contrast = 0;

    if(u16AddrMid % 4 != 0)
    {
        u16AddrMid += (u16AddrMid % 4);
    }

    while(u16AddrStart <= u16AddrEnd)
    {
        u16contrast = *((uint16_t *)(UTF16_GB2312_MEM_START_ADDR + u16AddrMid));

        if(u16utf16 == u16contrast)
        {
           *pu16utf16 = *((uint16_t *)(UTF16_GB2312_MEM_START_ADDR + u16AddrMid) + 1);
            return 0;
        }//往右边找
        else if(u16utf16 > u16contrast)
        {
            u16AddrStart = u16AddrMid;
            u16AddrMid = (u16AddrStart + u16AddrEnd) / 2;
            if(u16AddrMid % 4 != 0)
            {
                u16AddrMid -= (u16AddrMid % 4);
            }
        }//往左边找
        else if(u16utf16 < u16contrast)
        {
            u16AddrEnd = u16AddrMid;
            u16AddrMid = (u16AddrStart + u16AddrEnd) / 2;
            if(u16AddrMid % 4 != 0)
            {
                u16AddrMid += (u16AddrMid % 4);
            }
        }
    }
    return 1;
}

//计算字形偏移地址
uint32_t bsp_get_gb2312_sramaddr(uint16_t u16gb2312code)
{
    uint32_t u32Addr;
    switch(u16gb2312code & 0xF000)
    {
        case 0xA000:
        u32Addr = GB2312_SHADE_MEM_A_START_ADDR;
        //计算区码偏移
        u32Addr += (((u16gb2312code & 0xFF00) >> 8) - 0xA1) * (GB2312_FONT_DISTINGUISH_SIZE);
        //计算位码偏移
        u32Addr += ((u16gb2312code & 0x00FF) - 0xA1) * GB2312_FONT_SHADE_SIZE;
        break;
        default:
        u32Addr = GB2312_SHADE_MEM_B_START_ADDR;
        //计算区码偏移
        u32Addr += (((u16gb2312code & 0xFF00) >> 8) - 0xB0) * (GB2312_FONT_DISTINGUISH_SIZE);
        //计算位码偏移
        u32Addr += ((u16gb2312code & 0x00FF) - 0xA1) * GB2312_FONT_SHADE_SIZE;
        break;
    }
    
    return u32Addr;
}
